package cn.elwy.rcp.ui.dialog;

import java.io.PrintWriter;
import java.io.StringWriter;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

import cn.elwy.common.exception.MsgLevel;
import cn.elwy.common.exception.RunException;
import cn.elwy.common.util.AssertUtil;
import cn.elwy.rcp.core.model.ui.entity.MsgInfo;

/**
 * 自定义消息对话框类
 * @author HSQ
 */
public class MsgDialog {

  public static int open(Shell parent, MsgInfo msgInfo) {
    parent = initShell(parent);
    CMsgDialog dialog = new CMsgDialog(parent, msgInfo);
    return dialog.open();
  }

  public static int open(Shell parent, Throwable e) {
    return open(parent, getMsgInfo(e));
  }

  public static int open(Shell parent, String title, Throwable e) {
    MsgInfo msgInfo = getMsgInfo(e);
    msgInfo.setTitle(title);
    return open(parent, msgInfo);
  }

  public static int open(Shell parent, String title, String message, Throwable e) {
    MsgInfo msgInfo = getMsgInfo(e);
    msgInfo.setTitle(title);
    msgInfo.setMessage(message);
    return open(parent, msgInfo);
  }

  public static int open(Shell parent, MsgLevel msgLevel, String title, String message) {
    return open(parent, msgLevel, title, message, null);
  }

  public static int open(Shell parent, MsgLevel msgLevel, String title, String message, String detailMessage) {
    MsgInfo msgInfo = getMsgInfo(msgLevel, title, message, detailMessage);
    return open(parent, msgInfo);
  }

  public static void openAutoCloseDialog(Shell parent, String message) {
    openAutoCloseDialog(parent, null, message);
  }

  public static void openAutoCloseDialog(Shell parent, String title, String message) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.INFO, title, message);
    msgInfo.setAutoClose(true);
    open(parent, msgInfo);
  }

  public static void openInformation(Shell parent, String message) {
    openInformation(parent, null, message);
  }

  public static void openInformation(Shell parent, String title, String message) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.INFO, title, message);
    open(parent, msgInfo);
  }

  /**
   * 弹出一个确认对话框
   * @param parent
   * @param title
   * @param message
   * @return
   */
  public static boolean openConfirm(Shell parent, String title, String message) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.CONFIRM, title, message);
    return open(parent, msgInfo) == 0;
  }

  /**
   * 弹出一个询问对话框
   * @param parent
   * @param title
   * @param message
   * @return
   */
  public static boolean openQuestion(Shell parent, String title, String message) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.QUESTION, title, message);
    return open(parent, msgInfo) == 0;
  }

  /**
   * 弹出一个带有取消按钮的询问对话框
   * @param parent
   * @param title
   * @param message
   * @return
   */
  public static int openQuestionWithCancel(Shell parent, String title, String message) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.QUESTION_WITH_CANCEL, title, message);
    return open(parent, msgInfo);
  }

  /**
   * 弹出一个没有详细信息的错误对话框
   * @param parent
   * @param message
   */
  public static void openError(Shell parent, String message) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.ERROR, null, message, null);
    open(parent, msgInfo);
  }

  public static void openError(Shell parent, Throwable e) {
    MsgInfo msgInfo = getMsgInfo(e);
    msgInfo.setMsgLevel(MsgLevel.ERROR.toString());
    open(parent, msgInfo);
  }

  /**
   * 弹出一个没有详细信息的错误对话框
   * @param parent
   * @param title
   * @param message
   */
  public static void openError(Shell parent, String title, String message) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.ERROR, title, message, null);
    open(parent, msgInfo);
  }

  /**
   * 弹出一个有详细信息的错误对话框
   * @param parent
   * @param title
   * @param e
   */
  public static void openError(Shell parent, String title, Throwable e) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.ERROR, title, getMessage(e), getDetailMessage(e));
    open(parent, msgInfo);
  }

  /**
   * 弹出一个有详细信息的错误对话框
   * @param parent
   * @param title
   * @param message
   * @param e
   */
  public static void openError(Shell parent, String title, String message, Throwable e) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.ERROR, title, message, getDetailMessage(e));
    open(parent, msgInfo);
  }

  /**
   * 弹出一个有详细信息的错误对话框
   * @param parent
   * @param title
   * @param message
   * @param detailMessage
   */
  public static void openError(Shell parent, String title, String message, String detailMessage) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.ERROR, title, message, detailMessage);
    open(parent, msgInfo);
  }

  /**
   * 弹出一个没有详细信息的警告对话框
   * @param parent
   * @param message
   */
  public static void openWarn(Shell parent, String message) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.WARN, null, message, null);
    open(parent, msgInfo);
  }

  public static void openWarn(Shell parent, Throwable e) {
    MsgInfo msgInfo = getMsgInfo(e);
    msgInfo.setMsgLevel(MsgLevel.WARN.toString());
    open(parent, msgInfo);
  }

  /**
   * 弹出一个没有详细信息的警告对话框
   * @param parent
   * @param title
   * @param message
   */
  public static void openWarn(Shell parent, String title, String message) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.WARN, title, message, null);
    open(parent, msgInfo);
  }

  /**
   * 弹出一个有详细信息的警告对话框
   * @param parent
   * @param title
   * @param e
   */
  public static void openWarn(Shell parent, String title, Throwable e) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.WARN, title, getMessage(e), getDetailMessage(e));
    open(parent, msgInfo);
  }

  /**
   * 弹出一个有详细信息的警告对话框
   * @param parent
   * @param title
   * @param message
   * @param e
   */
  public static void openWarn(Shell parent, String title, String message, Throwable e) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.WARN, title, message, getDetailMessage(e));
    open(parent, msgInfo);
  }

  /**
   * 弹出一个有详细信息的警告对话框
   * @param parent
   * @param title
   * @param message
   * @param detailMessage
   */
  public static void openWarn(Shell parent, String title, String message, String detailMessage) {
    MsgInfo msgInfo = getMsgInfo(MsgLevel.WARN, title, message, detailMessage);
    open(parent, msgInfo);
  }

  public static MsgInfo getMsgInfo(Throwable e) {
    return getMsgInfo(getMsgLevel(e), null, getMessage(e), getDetailMessage(e));
  }

  public static MsgInfo getMsgInfo(MsgLevel msgLevel, String title, String message) {
    MsgInfo msgInfo = new MsgInfo();
    msgInfo.setMsgLevel(msgLevel.toString());
    msgInfo.setTitle(title);
    msgInfo.setMessage(message);

    return msgInfo;
  }

  public static MsgInfo getMsgInfo(MsgLevel msgLevel, String title, String message, String detailMessage) {
    MsgInfo msgInfo = new MsgInfo();
    msgInfo.setMsgLevel(msgLevel.toString());
    msgInfo.setTitle(title);
    msgInfo.setMessage(message);
    msgInfo.setDetailMessage(detailMessage);

    if (AssertUtil.isNotEmpty(detailMessage)) {
      msgInfo.setStyle(SWT.MAX | SWT.RESIZE);
    }
    return msgInfo;
  }

  private static MsgLevel getMsgLevel(Throwable e) {
    MsgLevel msgLevel = null;
    if (e instanceof RunException) {
      msgLevel = ((RunException) e).getMsgLevel();
    }
    if (msgLevel == null) {
      msgLevel = MsgLevel.ERROR;
    }
    return msgLevel;
  }

  private static Shell initShell(Shell parent) {
    if (parent == null) {
      parent = Display.getCurrent().getActiveShell();
    }
    if (parent == null) {
      parent = new Shell(Display.getCurrent());
    }
    parent.setFocus();
    return parent;
  }

  private static String getMessage(Throwable e) {
    if (e != null) {
      return e.getMessage() != null ? e.getMessage() : e.toString();
    }
    return null;
  }

  private static String getDetailMessage(Throwable e) {
    StringWriter stringWriter = new StringWriter();
    PrintWriter printwriter = new PrintWriter(stringWriter);
    if (e != null) {
      e.printStackTrace(printwriter);
      return stringWriter.toString();
    }
    return null;
  }

}
